<template>
  <div class="dashboard-container">
    <div class="dashboard-header">
      <a-button @click="backToDashboardList">
        <arrow-left-outlined />
        返回看板列表
      </a-button>
      <div class="dashboard-title" v-if="dashboard">{{ dashboard.title }}</div>
      <a-button type="primary" class="add-chart-btn" @click="showChartSelector = true">
        <plus-outlined />
        添加图表
      </a-button>
      <a-button type="primary" @click="saveDashboardData">
        <save-outlined />
        保存看板
      </a-button>
      <a-button type="primary" @click="toggleFullscreen">
        <fullscreen-outlined v-if="!isFullscreen" />
        <fullscreen-exit-outlined v-else />
        {{ isFullscreen ? '退出全屏' : '全屏显示' }}
      </a-button>
    </div>
    
    <div v-if="loading" class="loading-container">
      <a-spin size="large" />
    </div>
    
    <div v-else ref="dashboardContentRef" class="dashboard-content" :class="{ 'fullscreen': isFullscreen }" @click="handleDashboardClick">
      <GridLayout
        :layout="layout"
        :col-num="12"
        :row-height="30"
        :is-draggable="true"
        :is-resizable="true"
        :vertical-compact="true"
        :use-css-transforms="true"
        :margin="[10, 10]"
        @layout-updated="onLayoutUpdated"
        :style="{ height: containerHeight + 'px' }"
        class="dashboard-grid"
        :responsive="false"
      >
        <GridItem
          v-for="item in layout"
          :key="item.i"
          :x="item.x"
          :y="item.y"
          :w="item.w"
          :h="item.h"
          :i="item.i"
          class="dashboard-item"
          :class="{ 'selected-chart': selectedChartId === item.i, 'hovered-chart': hoveredChartId === item.i }"
          :is-draggable="true"
          :is-resizable="hoveredChartId === item.i || selectedChartId === item.i"
          drag-allow-from=".chart-header"
          resize-ignore-from=".chart-container"
          :style="{ border: (hoveredChartId === item.i || selectedChartId === item.i) ? '2px solid #40a9ff' : '2px solid transparent' }"
          @click.native.stop="selectChart(item.i)"
          @mouseover.native.stop="setHoveredChart(item.i)"
          @mouseleave.native.stop="setHoveredChart(null)"
        >
          <div class="chart-header">
            <span class="chart-title">{{ chartData[item.i]?.title || `图表 ${item.i}` }}</span>
            <div class="chart-actions">
              <a-button 
                type="text" 
                class="chart-action-btn" 
                :style="{ opacity: (selectedChartId === item.i || hoveredChartId === item.i) ? 1 : 0 }"
                @click.stop="openSettings(item.i)"
              >
                <setting-outlined />
              </a-button>
              <a-button 
                type="text" 
                class="chart-action-btn" 
                :style="{ opacity: (selectedChartId === item.i || hoveredChartId === item.i) ? 1 : 0 }"
                @click.stop="openFullView(item.i)"
              >
                <expand-outlined />
              </a-button>
              <a-button 
                type="text" 
                class="remove-chart-btn" 
                :style="{ opacity: (selectedChartId === item.i || hoveredChartId === item.i) ? 1 : 0 }"
                @click.stop="removeChart(item.i)"
              >
                <close-outlined />
              </a-button>
            </div>
          </div>
          <div class="chart-container">
            <component 
              :is="chartData[item.i]?.component" 
              :chart-id="item.i"
              :options="chartData[item.i]?.options"
              class="chart"
            />
          </div>
        </GridItem>
      </GridLayout>
    </div>
    
    <ChartSelector 
      v-if="showChartSelector" 
      @close="showChartSelector = false"
      @select="addChart"
    />

    <ChartSettingsDrawer
      :visible="showSettingsDrawer"
      :chart-type="currentChartType"
      :chart-id="currentChartId"
      :chart-options="currentChartOptions"
      :chart-title="currentChartTitle"
      @close="showSettingsDrawer = false"
      @save="updateChartSettings"
    />

    <!-- 图表全屏查看弹层 -->
    <a-modal
      v-model:visible="showFullViewModal"
      :title="fullViewChartTitle"
      :width="1000"
      :footer="null"
      centered
      class="chart-full-view-modal"
    >
      <div class="full-view-chart-container">
        <component 
          v-if="fullViewChartId && chartData[fullViewChartId]"
          :is="chartData[fullViewChartId]?.component" 
          :chart-id="fullViewChartId"
          :options="chartData[fullViewChartId]?.options"
          class="full-view-chart"
        />
      </div>
    </a-modal>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, onMounted, watch, nextTick, onUnmounted, markRaw } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import ChartSelector from '../components/ChartSelector.vue';
import ChartSettingsDrawer from '../components/ChartSettingsDrawer.vue';
import BarChart from '../components/charts/BarChart.vue';
import LineChart from '../components/charts/LineChart.vue';
import PieChart from '../components/charts/PieChart.vue';
import ScatterChart from '../components/charts/ScatterChart.vue';
import AreaChart from '../components/charts/AreaChart.vue';
import RadarChart from '../components/charts/RadarChart.vue';
import FunnelChart from '../components/charts/FunnelChart.vue';
import HeatmapChart from '../components/charts/HeatmapChart.vue';
import GaugeChart from '../components/charts/GaugeChart.vue';
import TreemapChart from '../components/charts/TreemapChart.vue';
import HorizontalBarChart from '../components/charts/HorizontalBarChart.vue';
import WordCloudChart from '../components/charts/WordCloudChart.vue';
import MetricChart from '../components/charts/MetricChart.vue';
import TableChart from '../components/charts/TableChart.vue';
import { GridLayout, GridItem } from 'vue3-grid-layout';
import { 
  PlusOutlined, 
  ArrowLeftOutlined, 
  CloseOutlined, 
  SaveOutlined, 
  SettingOutlined,
  FullscreenOutlined, 
  FullscreenExitOutlined,
  ExpandOutlined
} from '@ant-design/icons-vue';
import { message } from 'ant-design-vue';
import { getDashboardDetail, saveDashboard } from '../api/dashboard';
import type { Dashboard, Chart } from '../api/dashboard';

const route = useRoute();
const router = useRouter();
const dashboardId = ref(route.params.id as string);
const dashboard = ref<Dashboard | null>(null);
const loading = ref(true);
const dashboardContentRef = ref<HTMLElement | null>(null);
const isFullscreen = ref(false);

// 设置抽屉相关状态
const showSettingsDrawer = ref(false);
const currentChartId = ref('');
const currentChartType = ref('');
const currentChartOptions = ref<any>({});
const currentChartTitle = ref('');

// 图表全屏查看相关状态
const showFullViewModal = ref(false);
const fullViewChartId = ref('');
const fullViewChartTitle = ref('');

interface LayoutItem {
  x: number;
  y: number;
  w: number;
  h: number;
  i: string;
}

interface ChartDataItem {
  title: string;
  component: any;
  options: any;
  type?: string;
}

const showChartSelector = ref(false);
const layout = ref<LayoutItem[]>([]);
const chartData = reactive<Record<string, ChartDataItem>>({});
let nextId = 1;
const containerHeight = ref(500); // 初始高度

const selectedChartId = ref<string | null>(null);
const hoveredChartId = ref<string | null>(null);

const backToDashboardList = () => {
  router.push('/dashboard-list');
};

const chartTypes = {
  'bar': BarChart,
  'line': LineChart,
  'pie': PieChart,
  'scatter': ScatterChart,
  'area': AreaChart,
  'radar': RadarChart,
  'funnel': FunnelChart,
  'heatmap': HeatmapChart,
  'gauge': GaugeChart,
  'treemap': TreemapChart,
  'horizontal-bar': HorizontalBarChart,
  'word-cloud': WordCloudChart,
  'metric': MetricChart,
  'table': TableChart
};

// 获取看板数据
const fetchDashboardData = async () => {
  loading.value = true;
  try {
    const res = await getDashboardDetail(dashboardId.value);
    if (res.code === 200) {
      dashboard.value = res.data;
      
      // 重置布局和图表数据
      layout.value = [];
      Object.keys(chartData).forEach(key => {
        delete chartData[key];
      });
      
      // 配置存在的图表数据
      if (dashboard.value.charts && dashboard.value.charts.length > 0) {
        dashboard.value.charts.forEach((chart, index) => {
          const chartId = chart.id;
          
          // 添加到布局
          layout.value.push({
            x: (index % 3) * 4,  // 简单排列，每行3个图表
            y: Math.floor(index / 3) * 8,
            w: 4,
            h: 8,
            i: chartId
          });
          
          // 确保类型存在于chartTypes中
          if (chart.type && chartTypes[chart.type as keyof typeof chartTypes]) {
            // 添加到图表数据
            chartData[chartId] = {
              title: chart.title,
              component: markRaw(chartTypes[chart.type as keyof typeof chartTypes]),
              options: chart.options,
              type: chart.type
            };
          }
        });
        
        // 更新nextId
        nextId = dashboard.value.charts.length + 1;
      }
    } else {
      message.error(res.message || '获取看板数据失败');
    }
  } catch (error) {
    console.error('获取看板数据出错', error);
    message.error('获取看板数据出错');
  } finally {
    loading.value = false;
  }
};

// 保存看板数据
const saveDashboardData = async () => {
  if (!dashboard.value) return;
  
  try {
    // 构建图表数据
    const charts: Chart[] = layout.value.map(item => {
      const chart = chartData[item.i];
      return {
        id: item.i,
        title: chart.title,
        type: chart.type || '',
        options: chart.options
      };
    });
    
    const res = await saveDashboard({
      id: dashboardId.value,
      charts
    });
    
    if (res.code === 200) {
      message.success('保存成功');
    } else {
      message.error(res.message || '保存失败');
    }
  } catch (error) {
    console.error('保存看板出错', error);
    message.error('保存看板出错');
  }
};

// 计算容器高度
const calculateContainerHeight = () => {
  if (layout.value.length === 0) return 500; // 默认高度
  
  // 找到最大的y+h值来确定容器底部位置
  const bottomPosition = Math.max(...layout.value.map(item => (item.y + item.h) * 30 + item.y * 10));
  // 添加额外的底部间距，确保有足够空间
  const calculatedHeight = bottomPosition + 100; // 增加更多底部空间
  return Math.max(calculatedHeight, 500); // 最小高度为500px
};

const onLayoutUpdated = (newLayout: LayoutItem[]) => {
  layout.value = newLayout;
  // 计算并更新容器高度
  containerHeight.value = calculateContainerHeight();
};

// 监听布局变化，更新容器高度
watch(layout, () => {
  nextTick(() => {
    containerHeight.value = calculateContainerHeight();
  });
}, { deep: true, immediate: true });

const addChart = (chartType: any) => {
  const id = `chart-${nextId++}`;
  
  // 查找适合的位置，优先考虑右侧插入
  let newX = 0;
  let newY = 0;
  
  if (layout.value.length > 0) {
    // 获取当前所有行
    const rows: Record<number, LayoutItem[]> = {};
    layout.value.forEach(item => {
      if (!rows[item.y]) rows[item.y] = [];
      rows[item.y].push(item);
    });
    
    // 从第一行开始查找可插入的位置
    let found = false;
    Object.keys(rows).sort((a, b) => Number(a) - Number(b)).forEach(rowY => {
      if (found) return;
      
      // 获取该行最右边的位置
      const rowItems = rows[Number(rowY)];
      const rightmostX = Math.max(...rowItems.map(item => item.x + item.w));
      
      // 检查右侧是否有足够空间
      if (rightmostX + 4 <= 12) {
        newX = rightmostX;
        newY = Number(rowY);
        found = true;
      }
    });
    
    // 如果没有找到合适的位置，放在最底部
    if (!found) {
      newY = Math.max(...layout.value.map(item => item.y + item.h));
    }
  }
  
  const newItem: LayoutItem = {
    x: newX,
    y: newY,
    w: 4,
    h: 8,
    i: id
  };
  
  layout.value.push(newItem);
  
  // 确保chartType.type存在且有效
  if (!chartType.type || !chartTypes[chartType.type as keyof typeof chartTypes]) {
    console.error('无效的图表类型', chartType);
    return;
  }
  
  const newChartData = {
    title: `${chartType.label || '新图表'}`,
    component: markRaw(chartTypes[chartType.type as keyof typeof chartTypes]),
    options: chartType.defaultOptions || {},
    type: chartType.type
  };
  
  chartData[id] = newChartData;
  
  showChartSelector.value = false;
};

const removeChart = (id: string) => {
  const index = layout.value.findIndex(item => item.i === id);
  if (index !== -1) {
    layout.value.splice(index, 1);
    delete chartData[id];
    
    // 重新整理布局
    compactLayout();
  }
};

// 重新整理布局，使图表紧凑排列
const compactLayout = () => {
  if (layout.value.length === 0) return;
  
  // 按照y坐标排序，然后按照x坐标排序
  const sortedItems = [...layout.value].sort((a, b) => {
    if (a.y === b.y) return a.x - b.x;
    return a.y - b.y;
  });
  
  // 清空现有布局
  layout.value = [];
  
  // 重新计算每个图表的位置
  sortedItems.forEach((item, index) => {
    const row = Math.floor(index / 3); // 每行最多3个图表
    const col = index % 3;
    
    layout.value.push({
      ...item,
      x: col * 4, // 每个图表宽度为4
      y: row * 8  // 每个图表高度为8
    });
  });
  
  // 更新容器高度
  nextTick(() => {
    containerHeight.value = calculateContainerHeight();
  });
};

// 打开图表设置抽屉
const openSettings = (chartId: string) => {
  const chart = chartData[chartId];
  if (!chart || !chart.type) return;
  
  currentChartId.value = chartId;
  currentChartType.value = chart.type;
  currentChartOptions.value = chart.options;
  currentChartTitle.value = chart.title;
  
  showSettingsDrawer.value = true;
};

// 更新图表设置
const updateChartSettings = (data: { chartId: string; options: any }) => {
  const { chartId, options } = data;
  
  if (chartData[chartId]) {
    chartData[chartId].options = options;
    
    // 如果标题有变化，也需要更新
    if (options.title && options.title.text) {
      chartData[chartId].title = options.title.text;
    }
  }
};

// 全屏控制
const toggleFullscreen = () => {
  if (!dashboardContentRef.value) return;
  
  if (!isFullscreen.value) {
    // 进入全屏
    if (dashboardContentRef.value.requestFullscreen) {
      dashboardContentRef.value.requestFullscreen();
    } else if ((dashboardContentRef.value as any).mozRequestFullScreen) {
      (dashboardContentRef.value as any).mozRequestFullScreen();
    } else if ((dashboardContentRef.value as any).webkitRequestFullscreen) {
      (dashboardContentRef.value as any).webkitRequestFullscreen();
    } else if ((dashboardContentRef.value as any).msRequestFullscreen) {
      (dashboardContentRef.value as any).msRequestFullscreen();
    }
    isFullscreen.value = true;
  } else {
    // 退出全屏
    if (document.exitFullscreen) {
      document.exitFullscreen();
    } else if ((document as any).mozCancelFullScreen) {
      (document as any).mozCancelFullScreen();
    } else if ((document as any).webkitExitFullscreen) {
      (document as any).webkitExitFullscreen();
    } else if ((document as any).msExitFullscreen) {
      (document as any).msExitFullscreen();
    }
    isFullscreen.value = false;
  }
};

// 监听全屏变化事件
const handleFullscreenChange = () => {
  isFullscreen.value = !!document.fullscreenElement;
};

const selectChart = (id: string) => {
  if (selectedChartId.value === id) {
    selectedChartId.value = null; // 再次点击已选中的图表会取消选中
  } else {
    selectedChartId.value = id;
  }
};

const handleDashboardClick = (event: MouseEvent) => {
  // 如果点击的是dashboard-content元素本身而不是其子元素，则取消选中
  if (event.target === event.currentTarget) {
    selectedChartId.value = null;
  }
};

const setHoveredChart = (id: string | null) => {
  // 防止频繁更新导致的重排
  if (hoveredChartId.value !== id) {
    hoveredChartId.value = id;
  }
};

// 打开图表全屏查看
const openFullView = (chartId: string) => {
  const chart = chartData[chartId];
  if (!chart) return;
  
  fullViewChartId.value = chartId;
  fullViewChartTitle.value = chart.title || `图表 ${chartId}`;
  showFullViewModal.value = true;
};

onMounted(() => {
  // 初始化容器高度
  containerHeight.value = calculateContainerHeight();
  
  // 获取看板数据
  fetchDashboardData();
  
  // 添加全屏变化事件监听
  document.addEventListener('fullscreenchange', handleFullscreenChange);
  document.addEventListener('webkitfullscreenchange', handleFullscreenChange);
  document.addEventListener('mozfullscreenchange', handleFullscreenChange);
  document.addEventListener('MSFullscreenChange', handleFullscreenChange);
});

onUnmounted(() => {
  // 移除全屏变化事件监听
  document.removeEventListener('fullscreenchange', handleFullscreenChange);
  document.removeEventListener('webkitfullscreenchange', handleFullscreenChange);
  document.removeEventListener('mozfullscreenchange', handleFullscreenChange);
  document.removeEventListener('MSFullscreenChange', handleFullscreenChange);
});
</script>

<style scoped>
.dashboard-container {
  display: flex;
  flex-direction: column;
  width: 100%;
  height: 100%;
  overflow: hidden;
  padding: 0;
  margin: 0;
}

.dashboard-header {
  display: flex;
  align-items: center;
  margin-bottom: 16px;
  gap: 12px;
  padding: 0;
}

.dashboard-title {
  font-size: 18px;
  font-weight: bold;
  margin-left: 12px;
}

.add-chart-btn {
  margin-left: auto;
}

.dashboard-content {
  flex: 1;
  overflow: auto;
  border-radius: 4px;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.05);
  padding: 4px;
  position: relative;
}

.dashboard-content.fullscreen {
  z-index: 9999;
  background-color: white;
  padding: 20px;
}

.fullscreen-exit-btn {
  position: absolute;
  bottom: 20px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 1000;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}

.fullscreen-exit-btn .ant-btn {
  font-weight: bold;
  padding: 0 20px;
}

.loading-container {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 400px;
  width: 100%;
}

/* 自定义滚动条样式 */
.dashboard-content::-webkit-scrollbar {
  width: 10px;
  height: 10px;
}

.dashboard-content::-webkit-scrollbar-track {
  background: #f1f1f1;
  border-radius: 5px;
}

.dashboard-content::-webkit-scrollbar-thumb {
  background: #c1c1c1;
  border-radius: 5px;
  border: 2px solid #f1f1f1;
}

.dashboard-content::-webkit-scrollbar-thumb:hover {
  background: #a8a8a8;
}

.dashboard-grid {
  width: 100%;
  border-radius: 4px;
  min-height: 500px;
  overflow: visible;
  transition: height 0.3s ease;
  position: relative;
}

.dashboard-item {
  background-color: white;
  border-radius: 4px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  position: relative;
  /* 固定尺寸不变化 */
  outline: 0 none;
  padding: 0;
  margin: 0;
  transition: border-color 0.3s ease !important;
  border: 2px solid transparent !important;
  box-sizing: border-box !important;
}

/* 通过!important确保CSS优先级 */
:deep(.dashboard-item:hover) {
  border: 2px solid #40a9ff !important;
  box-shadow: 0 0 8px rgba(64, 169, 255, 0.5) !important;
  z-index: 10 !important;
}

/* 确保鼠标悬停时有高亮边框 */
.dashboard-grid :deep(.vue-grid-item:hover) {
  border: 2px solid #40a9ff !important;
  box-shadow: 0 0 8px rgba(64, 169, 255, 0.5) !important;
  z-index: 10 !important;
}

/* 选中样式优先级高于悬停 */
.dashboard-item.selected-chart {
  border: 2px solid #1890ff !important;
  box-shadow: 0 0 8px rgba(24, 144, 255, 0.5) !important;
  z-index: 10 !important;
}

.chart-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 8px;
  cursor: move;
  user-select: none;
  height: 40px;
  box-sizing: border-box;
}

.chart-title {
  font-weight: 500;
  font-size: 14px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 80%;
}

.chart-actions {
  display: flex;
  align-items: center;
  min-width: 64px;
  justify-content: flex-end;
}

.chart-action-btn,
.remove-chart-btn {
  color: #999;
  margin-left: 4px;
  transition: opacity 0.2s ease, color 0.2s ease;
}

.chart-action-btn:hover {
  color: #1890ff;
}

.remove-chart-btn:hover {
  color: #ff4d4f;
}

.chart-container {
  flex: 1;
  padding: 10px;
  overflow: hidden;
  position: relative;
}

.chart {
  width: 100%;
  height: 100%;
  position: absolute;
  top: 10px;
  left: 10px;
  right: 10px;
  bottom: 10px;
}

/* 强制样式覆盖 */
.dashboard-grid .vue-grid-item .vue-resizable-handle {
  opacity: 0 !important;
  z-index: 100;
  background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="10" height="10"><path fill="%231890ff" d="M0,0 L10,0 L10,10 L0,10 Z"/><path fill="white" d="M8,2 L8,8 L2,8 Z"/></svg>');
  background-position: bottom right;
  background-repeat: no-repeat;
  transition: opacity 0.3s;
}

.dashboard-grid .vue-grid-item:hover .vue-resizable-handle {
  opacity: 1 !important;
}

.dashboard-item:hover > .vue-resizable-handle,
.dashboard-item.hovered-chart > .vue-resizable-handle {
  opacity: 1 !important;
}

.chart-full-view-modal {
  .full-view-chart-container {
    height: 600px;
    overflow: hidden;
    position: relative;
  }
  
  .full-view-chart {
    width: 100%;
    height: 100%;
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
  }
}
</style> 